Display the progressive load
authorHavoc Pennington <hp@pobox.com>
Wed, 27 Oct 1999 19:42:34 +0000 (19:42 +0000)
committerHavoc Pennington <hp@src.gnome.org>
Wed, 27 Oct 1999 19:42:34 +0000 (19:42 +0000)
1999-10-27  Havoc Pennington  <hp@pobox.com>

* src/testpixbuf.c (main): Display the progressive load

* src/io-png.c (setup_png_transformations): Break transformation
code into separate function
(png_info_callback): Use setup_png_transformations

demos/testpixbuf.c
gdk-pixbuf/ChangeLog
gdk-pixbuf/io-png.c

index fc6d0aa397320238137805625c302f4eb73bd9ac..83e1444ce11e518aba41b64abdcf5fcb29bbaea8 100644 (file)
@@ -351,7 +351,7 @@ config_func (GtkWidget *drawing_area, GdkEventConfigure *event, gpointer data)
 #endif
 }
 
-static void
+static GtkWidget*
 new_testrgb_window (GdkPixbuf *pixbuf)
 {
        GtkWidget *window;
@@ -400,6 +400,33 @@ new_testrgb_window (GdkPixbuf *pixbuf)
        gtk_widget_show (vbox);
 
        gtk_widget_show (window);
+
+        return window;
+}
+
+static gint
+update_timeout(gpointer data)
+{
+        GtkWidget** window_loc = data;
+
+        if (*window_loc != NULL) {
+                gtk_widget_queue_draw(*window_loc);
+        }
+}
+
+static void
+progressive_prepared_callback(GdkPixbufLoader* loader, gpointer data)
+{
+        GtkWidget** retloc = data;
+        GdkPixbuf* pixbuf;
+
+        pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
+        g_assert(pixbuf != NULL);
+
+        gdk_pixbuf_ref(pixbuf); /* for the RGB window */
+        *retloc = new_testrgb_window(pixbuf);
+
+        return;
 }
 
 int
@@ -453,21 +480,48 @@ main (int argc, char **argv)
                        }
                }
 
-               pixbuf_loader = gdk_pixbuf_loader_new ();
-               file = fopen (argv[1], "r");
-               g_assert (file != NULL);
-               
-               while (TRUE) {
-                       val = fgetc (file);
-                       if (val == EOF)
-                               break;
-                       buf = (guint) val;
-                       if (gdk_pixbuf_loader_write (GDK_PIXBUF_LOADER (pixbuf_loader), &buf, 1) == FALSE)
-                               break;
-               }
-               gdk_pixbuf_loader_close (GDK_PIXBUF_LOADER (pixbuf_loader));
-               gtk_object_destroy (pixbuf_loader);
-               fclose (file);
+                {
+                        GtkWidget* rgb_window = NULL;
+                        guint timeout;
+                        
+                        pixbuf_loader = gdk_pixbuf_loader_new ();
+
+                        gtk_signal_connect(GTK_OBJECT(pixbuf_loader),
+                                           "area_prepared",
+                                           GTK_SIGNAL_FUNC(progressive_prepared_callback),
+                                           &rgb_window);
+
+                        timeout = gtk_timeout_add(1000, update_timeout, &rgb_window);
+                        
+                        file = fopen (argv[1], "r");
+                        g_assert (file != NULL);
+                        
+                        while (TRUE) {
+                                val = fgetc (file);
+                                if (val == EOF)
+                                        break;
+                                buf = (guint) val;
+
+                                fflush(stdout);
+
+                                printf(".");
+                                fflush(stdout);
+                                
+                                if (gdk_pixbuf_loader_write (GDK_PIXBUF_LOADER (pixbuf_loader), &buf, 1) == FALSE)
+                                        break;
+
+                                while (gtk_events_pending())
+                                        gtk_main_iteration();
+
+                        }
+                        gtk_timeout_remove(timeout);
+                        gdk_pixbuf_loader_close (GDK_PIXBUF_LOADER (pixbuf_loader));
+                        gtk_object_destroy (GTK_OBJECT(pixbuf_loader));
+                        fclose (file);
+
+                        if (rgb_window != NULL)
+                                gtk_widget_queue_draw(rgb_window);
+                }
                
        }
 
index a9f5f9497bcb12c313788b4ac44078046a016309..cc4fb9b36cea4d6c2f9f4c24c885a283f0ed6589 100644 (file)
@@ -1,3 +1,27 @@
+1999-10-27  Havoc Pennington  <hp@pobox.com>
+
+       * src/testpixbuf.c (main): Display the progressive load
+
+       * src/io-png.c (setup_png_transformations): Break transformation 
+       code into separate function
+       (png_info_callback): Use setup_png_transformations
+       
+
+1999-10-27  Havoc Pennington  <hp@pobox.com>
+
+       * src/gdk-pixbuf-io.c (gdk_pixbuf_new_from_xpm_data): Check
+       properly whether the XPM module has already been loaded
+       (gdk_pixbuf_new_from_file): Check properly if loader module 
+       was already loaded (was checking if load symbol was present
+       in order to decide whether to re-load; should check module !=
+       NULL, then load != NULL)        
+       (image_handler_load): Check in present working directory, 
+       makes it easier to debug for now
+       (file_formats): This array initializer was seriously on crack, 
+       was assigning a function pointer to a GModule*
+
+       * src/testpixbuf.c (main): Change type of pixbuf_loader to GdkPixbufLoader*
+       
 1999-10-27  Havoc Pennington  <hp@pobox.com>
 
        * src/gdk-pixbuf-loader.c (gdk_pixbuf_loader_finalize): 
index fed2e7e806bdfeb9c600e2900f2a2c4f5e4b9b26..c6a8289c3e9fbfa84405ee73f1c3918849ca54b9 100644 (file)
 
 \f
 
+static void
+setup_png_transformations(png_structp png_read_ptr, png_infop png_info_ptr,
+                          gboolean *fatal_error_occurred,
+                          png_uint_32* width_p, png_uint_32* height_p,
+                          int* color_type_p)
+{
+        png_uint_32 width, height;
+        int bit_depth, color_type, interlace_type, compression_type, filter_type;
+        int channels;
+        
+        /* Get the image info */
+
+        png_get_IHDR (png_read_ptr, png_info_ptr,
+                      &width, &height,
+                      &bit_depth,
+                      &color_type,
+                      &interlace_type,
+                      &compression_type,
+                      &filter_type);
+
+        /* set_expand() basically needs to be called unless
+           we are already in RGB/RGBA mode
+        */
+        if (color_type == PNG_COLOR_TYPE_PALETTE &&
+            bit_depth <= 8) {
+
+                /* Convert indexed images to RGB */
+                png_set_expand (png_read_ptr);
+
+        } else if (color_type == PNG_COLOR_TYPE_GRAY &&
+                   bit_depth < 8) {
+
+                /* Convert grayscale to RGB */
+                png_set_expand (png_read_ptr);
+
+        } else if (png_get_valid (png_read_ptr, 
+                                  png_info_ptr, PNG_INFO_tRNS)) {
+
+                /* If we have transparency header, convert it to alpha
+                   channel */
+                png_set_expand(png_read_ptr);
+                
+        } else if (bit_depth < 8) {
+
+                /* If we have < 8 scale it up to 8 */
+                png_set_expand(png_read_ptr);
+
+
+                /* Conceivably, png_set_packing() is a better idea;
+                 * God only knows how libpng works
+                 */
+        }
+
+        /* If we are 16-bit, convert to 8-bit */
+        if (bit_depth == 16) {
+                png_set_strip_16(png_read_ptr);
+        }
+
+        /* If gray scale, convert to RGB */
+        if (color_type == PNG_COLOR_TYPE_GRAY ||
+            color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
+                png_set_gray_to_rgb(png_read_ptr);
+        }
+        
+        /* If interlaced, handle that */
+        if (interlace_type != PNG_INTERLACE_NONE) {
+                png_set_interlace_handling(png_read_ptr);
+        }
+        
+        /* Update the info the reflect our transformations */
+        png_read_update_info(png_read_ptr, png_info_ptr);
+        
+        png_get_IHDR (png_read_ptr, png_info_ptr,
+                      &width, &height,
+                      &bit_depth,
+                      &color_type,
+                      &interlace_type,
+                      &compression_type,
+                      &filter_type);
+
+        *width_p = width;
+        *height_p = height;
+        *color_type_p = color_type;
+        
+#ifndef G_DISABLE_CHECKS
+        /* Check that the new info is what we want */
+        
+        if (bit_depth != 8) {
+                g_warning("Bits per channel of transformed PNG is %d, not 8.", bit_depth);
+                *fatal_error_occurred = TRUE;
+                return;
+        }
+
+        if ( ! (color_type == PNG_COLOR_TYPE_RGB ||
+                color_type == PNG_COLOR_TYPE_RGB_ALPHA) ) {
+                g_warning("Transformed PNG not RGB or RGBA.");
+                *fatal_error_occurred = TRUE;
+                return;
+        }
+
+        channels = png_get_channels(png_read_ptr, png_info_ptr);
+        if ( ! (channels == 3 || channels == 4) ) {
+                g_warning("Transformed PNG has %d channels, must be 3 or 4.", channels);
+                *fatal_error_occurred = TRUE;
+                return;
+        }
+#endif
+}
+
 /* Destroy notification function for the libart pixbuf */
 static void
 free_buffer (gpointer user_data, gpointer data)
@@ -43,6 +152,7 @@ image_load (FILE *f)
 {
        png_structp png_ptr;
        png_infop info_ptr, end_info;
+        gboolean failed = FALSE;
        gint i, depth, ctype, inttype, passes, bpp;
        png_uint_32 w, h;
        png_bytepp rows;
@@ -71,41 +181,14 @@ image_load (FILE *f)
 
        png_init_io (png_ptr, f);
        png_read_info (png_ptr, info_ptr);
-       png_get_IHDR (png_ptr, info_ptr, &w, &h, &depth, &ctype, &inttype, NULL, NULL);
-
-       /* Ok, we want to work with 24 bit images.
-        * However, PNG can vary depth per channel.
-        * So, we use the png_set_expand function to expand
-        * everything into a format libart expects.
-        * We also use png_set_strip_16 to reduce down to 8 bit/chan.
-        */
-       if (ctype == PNG_COLOR_TYPE_PALETTE && depth <= 8)
-               png_set_expand (png_ptr);
-
-       if (ctype == PNG_COLOR_TYPE_GRAY && depth < 8)
-               png_set_expand (png_ptr);
-
-       if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) {
-               png_set_expand (png_ptr);
-               g_warning ("FIXME: We are going to crash");
-       }
-
-       if (depth == 16)
-               png_set_strip_16 (png_ptr);
 
-       /* We also have png "packing" bits into bytes if < 8 */
-       if (depth < 8)
-               png_set_packing (png_ptr);
-
-       /* Lastly, if the PNG is greyscale, convert to RGB */
-       if (ctype == PNG_COLOR_TYPE_GRAY || ctype == PNG_COLOR_TYPE_GRAY_ALPHA)
-               png_set_gray_to_rgb (png_ptr);
-
-       /* ...and if we're interlaced... */
-       passes = png_set_interlace_handling (png_ptr);
-
-       png_read_update_info (png_ptr, info_ptr);
+        setup_png_transformations(png_ptr, info_ptr, &failed, &w, &h, &ctype);
 
+        if (failed) {
+                png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
+                return NULL;
+        }
+        
        if (ctype & PNG_COLOR_MASK_ALPHA)
                bpp = 4;
        else
@@ -197,7 +280,7 @@ image_begin_load (ModulePreparedNotifyFunc func, gpointer user_data)
                 return NULL;
         }
 
-        /* Create the two auxiliary context structs */
+        /* Create the auxiliary context struct */
 
         lc->png_info_ptr = png_create_info_struct(lc->png_read_ptr);
 
@@ -253,108 +336,30 @@ png_info_callback   (png_structp png_read_ptr,
 {
         LoadContext* lc;
         png_uint_32 width, height;
-        int bit_depth, color_type, filter_type,
-          compression_type, interlace_type, channels;
+        int color_type;
         gboolean have_alpha = FALSE;
+        gboolean failed = FALSE;
         
         lc = png_get_progressive_ptr(png_read_ptr);
 
         if (lc->fatal_error_occurred)
                 return;
         
-        /* Get the image info */
-
-        png_get_IHDR (lc->png_read_ptr, lc->png_info_ptr,
-                      &width, &height,
-                      &bit_depth,
-                      &color_type,
-                      &interlace_type,
-                      &compression_type,
-                      &filter_type);
-
-        /* set_expand() basically needs to be called unless
-           we are already in RGB/RGBA mode
-        */
-        if (color_type == PNG_COLOR_TYPE_PALETTE &&
-            bit_depth <= 8) {
-
-                /* Convert indexed images to RGB */
-                png_set_expand (lc->png_read_ptr);
-
-        } else if (color_type == PNG_COLOR_TYPE_GRAY &&
-                   bit_depth < 8) {
-
-                /* Convert grayscale to RGB */
-                png_set_expand (lc->png_read_ptr);
 
-        } else if (png_get_valid (lc->png_read_ptr, 
-                                  lc->png_info_ptr, PNG_INFO_tRNS)) {
-
-                /* If we have transparency header, convert it to alpha
-                   channel */
-                png_set_expand(lc->png_read_ptr);
-                
-        } else if (bit_depth < 8) {
+        setup_png_transformations(lc->png_read_ptr,
+                                  lc->png_info_ptr,
+                                  &failed,
+                                  &width, &height, &color_type);
 
-                /* If we have < 8 scale it up to 8 */
-                png_set_expand(lc->png_read_ptr);
-
-
-                /* Conceivably, png_set_packing() is a better idea;
-                 * God only knows how libpng works
-                 */
-        }
-
-        /* If we are 16-bit, convert to 8-bit */
-        if (bit_depth == 16) {
-                png_set_strip_16(lc->png_read_ptr);
+        if (failed) {
+                lc->fatal_error_occurred = TRUE;
+                return;
         }
 
-        /* If gray scale, convert to RGB */
-        if (color_type == PNG_COLOR_TYPE_GRAY ||
-            color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
-                png_set_gray_to_rgb(lc->png_read_ptr);
-        }
-        
         /* If we have alpha, set a flag */
         if (color_type & PNG_COLOR_MASK_ALPHA)
-          have_alpha = TRUE;
-
-        /* Update the info the reflect our transformations */
-        png_read_update_info(lc->png_read_ptr, lc->png_info_ptr);
+                have_alpha = TRUE;
         
-        png_get_IHDR (lc->png_read_ptr, lc->png_info_ptr,
-                      &width, &height,
-                      &bit_depth,
-                      &color_type,
-                      &interlace_type,
-                      &compression_type,
-                      &filter_type);
-
-#ifndef G_DISABLE_CHECKS
-        /* Check that the new info is what we want */
-        
-        if (bit_depth != 8) {
-                g_warning("Bits per channel of transformed PNG is %d, not 8.", bit_depth);
-                lc->fatal_error_occurred = TRUE;
-                return;
-        }
-
-        if ( ! (color_type == PNG_COLOR_TYPE_RGB ||
-                color_type == PNG_COLOR_TYPE_RGB_ALPHA) ) {
-                g_warning("Transformed PNG not RGB or RGBA.");
-                lc->fatal_error_occurred = TRUE;
-                return;
-        }
-
-        channels = png_get_channels(lc->png_read_ptr, lc->png_info_ptr);
-        if ( ! (channels == 3 || channels == 4) ) {
-                g_warning("Transformed PNG has %d channels, must be 3 or 4.", channels);
-                lc->fatal_error_occurred = TRUE;
-                return;
-        }
-#endif
-
         lc->pixbuf = gdk_pixbuf_new(have_alpha, width, height);
 
         if (lc->pixbuf == NULL) {
@@ -388,7 +393,7 @@ png_row_callback   (png_structp png_read_ptr,
                 return;
                 
         old_row = lc->pixbuf->art_pixbuf->pixels + (row_num * lc->pixbuf->art_pixbuf->rowstride);
-        
+
         png_progressive_combine_row(lc->png_read_ptr, old_row, new_row);
 }